package kz.edu.sdu.itech.pcs.client;

import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;

import kz.edu.sdu.itech.pcs.common.MessageType;

import org.apache.log4j.Logger;

public class WorkerProtocol extends Thread implements Runnable {
   public static Logger log = Logger.getLogger(WorkerProtocol.class);

   static String IM_MSG = "IM:%s";
   String host;
   int port;
   WorkerClient client;

   Socket socket;

   Scanner in;
   PrintWriter out;

   public WorkerProtocol(WorkerClient client, String ip, int port) {
      this.client = client;
      client.getThread().start();
      host = ip;
      this.port = port;
   }

   public void connect() {
      try {
         socket = new Socket(host, port);
         in = new Scanner(socket.getInputStream());
         out = new PrintWriter(socket.getOutputStream());
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   public static void sleep(int x) {
      try {
         Thread.sleep(x);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }

   public void close() {
      try {
         in.close();
         out.close();
         socket.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   public MessageToServer getResponse(MessageToWorker req) {
      MessageToServer res = new MessageToServer(this);
      res.setType(req.getType());
      if (req.getType().equals(MessageType.HI)) {
         res.addArg("NAME", client.getTitle());
      } else if (req.getType().equals(MessageType.START)) {
         HashMap<String, String> map = req.getArgs();

         //set alphabet
         String alf = map.get("alphabet");
         client.getAlphabet().clear();
         client.getAlphabet().add(alf);

         //
         String len = map.get("len");
         client.setLen(Integer.parseInt(len));

         String start = map.get("start");
         client.setStart(Integer.parseInt(start));
         String end = map.get("end");
         client.setEnd(Integer.parseInt(end));

         String hash = map.get("hash");
         client.setHash(Integer.parseInt(hash));

         client.startWork();

         res.addArg("msg", "OK");
      } else if (req.getType().equals(MessageType.STOP)) {
         client.stopWork();
         log.debug("stopping..");
         while (client.getThread().getState().equals(Thread.State.RUNNABLE)) {
            log.debug("waiting till stops");
            sleep(100);
         }
         log.debug("STOPED");
         res.addArg("msg", "OK");
      } else if (req.getType().equals(MessageType.COND)) {
         res.addArg("STATUS", client.getStatus());
         if (!client.getStatus().equals(WorkerClient.NOT_STARTED)) {
            res.addArg("CURRENT", String.format("%d", client.getCurrent()));
            res.addArg("COUNT", String.format("%d", client.getCount()));
         }
      } else if (req.getType().equals(MessageType.BYE)) {
         res.addArg("msg", "nu poka!");
         log.debug("Server tell us BYE");
         AppProps.DONE = true;
      }
      return res;
   }

   @Override
   public void run() {
      log.debug("STARTING");
      connect();
      MessageToWorker req = new MessageToWorker(this);
      while (!AppProps.DONE) {
         if (req.read()) {
            MessageToServer res = getResponse(req);
            while (!AppProps.DONE && !res.send()) {
               try {
                  log.debug("Could not send response");
                  Thread.sleep(1000);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }
         } else
            break;
      }
      close();
   }
}
